<?php

namespace app\files\controller;

use think\Request;
use think\Response;

/**
 * 通用文件处理
 */
class File
{

    protected $request;
    protected $config;

    public function __construct(Request $request)
    {
        $this->request = $request;
        $this->config  = config('upload_file');
    }

    /**
     * 输出返回数据
     * @access protected
     * @param mixed     $data 要返回的数据
     * @param String    $type 返回类型 JSON XML
     * @param integer   $code HTTP状态码
     * @return Response
     */
    protected function response($msg, $code = 200, $data = '', $type = 'json')
    {
        $result = [
            'code'  => $code,
            'msg'   => $msg,
            'data'  => $data,
            '_link' => '',
        ];
        if ($data) {
            if (is_array($data)) {
                foreach ($data as $key => $value) {
                    $result['_link'][] = getFileUrl($value, 'file');
                }
            } else {
                $result['_link'] = getFileUrl($data, 'file');
            }
        }
        $header = ['x_end_time' => $this->request->time()];
        return Response::create($result, $type)->code($code)->header($header);
    }

    /**
     * 文件下载
     *
     * @return \think\Response
     */
    public function index($sha1, $type = 128)
    {
        $info = db('file')->where('sha1', $sha1)->find();
        if (empty($info)) {
            return $this->response('指定文件不存在!', 404);
        }
        $path = './.' . $info['path'];
        if (!is_file($path)) {
            return $this->response('指定文件已被系统删除!', 404);
        }
        $temp = './../runtime/music/' . substr($sha1, 0, 2) . DS . $type . '_' . $sha1 . '.' . $info['ext'];

        if (is_file($temp)) {
            $path = $temp;
        }
        header("Location:" . $path);
        exit();

    }
    /**
     * php自实行断点续传下载  目前在谷歌浏览器和ios下有bug暂时采用302
     * @param type $path
     * @param type $info
     */
    private function down($path, $info)
    {
        $start = null;
        $end   = $info['size'] - 1;
        if (isset($_SERVER['HTTP_RANGE']) && ($_SERVER['HTTP_RANGE'] != "") && preg_match("/^bytes=([0-9]+)-([0-9]*)$/i", $_SERVER['HTTP_RANGE'], $match) && ($match[1] < $info['size']) && ($match[2] < $info['size'])) {
            $start = $match[1];
            if (!empty($match[2])) {
                $end = $match[2];
            }

        }
        header("Cache-control: public");
        header("Pragma: public");
        set_time_limit(0);
        $chunkSize = 8 * 1024 * 1024;
        $handle    = fopen($path, "rb");
        if ($start === null) {
            header("HTTP/1.1 200 OK");
            header("Content-Length: " . $info['size']);
            header("Accept-Ranges: bytes");
            while (!feof($handle)) {
                echo fread($handle, $chunkSize);
                flush();
            }
            fclose($handle);
        } else {
            header("HTTP/1.1 206 Partial Content");
            header("Accept-Ranges: bytes");
            header("Content-Length: " . ($end - $start + 1));
            header("Content-Ranges: bytes " . $start . "-" . $end . "/" . $info['size']);
            fseek($handle, $start);
            while (!feof($handle) && ($pos = ftell($handle)) <= $end) {
                if ($pos + $chunkSize > $end) {
                    $chunkSize = $end - $pos + 1;
                }
                echo fread($handle, $chunkSize);
                flush(); // Free up memory. Otherwise large files will trigger PHP's memory limit.
            }
            fclose($handle);
        }
    }

    /**
     * 文件下载
     *
     * @return \think\Response
     */
    public function download($sha1)
    {
        $info = db('file')->where('sha1', $sha1)->find();
        if (empty($info)) {
            return $this->response('指定文件不存在!', 404);
        }
        $path = './.' . $info['path'];
        if (!is_file($path)) {
            return $this->response('指定文件已被系统删除!', 404);
        }
        $content                  = file_get_contents($path);
        $header['Content-Length'] = $info['size'];
        if (preg_match('/MSIE/', $_SERVER['HTTP_USER_AGENT'])) {
            //for IE
            $header['Content-Disposition'] = 'attachment; filename="' . rawurlencode(time() . '.' . $info['ext']) . '"';
        } else {
            $header['Content-Disposition'] = 'attachment; filename="' . time() . '.' . $info['ext'] . '"';
        }
        return response($content, 200, $header)->contentType($info['mime']);
    }

    /**
     * 文件上传
     */
    public function upload()
    {
        $files = $this->request->file($this->config['name']);
        if (empty($files)) {
            return $this->response('没有上传的文件!', 400);
        }
        $type = $this->request->param('type', 'single');
        if ($type == 'multi') {
            return $this->multi($files);
        } else {
            return $this->single($files);
        }
    }

    /**
     * 单文件上传
     * @param type $file file对象
     * @return type
     */
    private function single($file)
    {
        if (is_array($file)) {
            $file = current($file);
        }
        if ($file->check($this->config['rule']) === false) {
            return $this->response($file->getMime() . $file->getError() . $this->config['rule']['type'], 400);
        }
        $info = db('file')->where('sha1', $file->hash())->find();
        if (empty($info)) {
            $res = $file->rule($this->config['savename'])->move(ROOT_PATH . $this->config['path']);
            if ($res === false) {
                return $this->response($file->getError(), 400);
            }
            $info = [
                'path'        => $this->config['path'] . $res->getSaveName(),
                'create_time' => $this->request->time(),
                'sha1'        => $res->hash(),
                'size'        => $res->getSize(),
                'mime'        => $res->getMime(),
                'ext'         => $res->getExtension(),
            ];
            db('file')->insert($info);
        }

        return $this->response('上传成功!', 200, $file->hash());
    }

    /**
     * 多文件上传
     * @param type $files file对象集合
     * @return type
     */
    private function multi($files)
    {
        if (!is_array($files)) {
            $files = [$files];
        }
        $savedata = [];
        $data     = [];
        foreach ($files as $file) {
            if ($file->check($this->config['rule']) === false) {
                return $this->response($file->getError(), 400);
            }
            $info = db('picture')->where('sha1', $file->hash())->find();
            if (empty($info)) {
                $res = $file->rule($this->config['savename'])->move(ROOT_PATH . $this->config['path']);
                if ($res === false) {
                    return $this->response($file->getError(), 400);
                }
                $savedata[] = [
                    'path'        => $this->config['path'] . $res->getSaveName(),
                    'create_time' => $this->request->time(),
                    'sha1'        => $res->hash(),
                    'size'        => $res->getSize(),
                    'mime'        => $res->getMime(),
                    'ext'         => $res->getExtension(),
                ];
            }
            $data[] = $file->hash();
        }
        if (!empty($savedata)) {
            db('file')->insertAll($savedata);
        }
        return $this->response('上传成功!', 200, $data);
    }

    /**
     * 文件上传(断点续传)
     */
    public function uploads($part, $sha1)
    {

    }

}
